#region File Header
//----------------------------------------------------------------
// Copyright (C) 2002 Stefan Kyntchev
// All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY 
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT 
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
// FITNESS FOR A PARTICULAR PURPOSE.
//----------------------------------------------------------------
#endregion File Header

using System;
using System.Collections;

namespace AirWeb.Security
{
	/// <summary>
	/// Represents a Role (user Group). Defines a set of Allow/Deny rights for a given user.
	/// </summary>

	[Serializable]
	public class Role
	{
		string m_Name;
		string m_Description;

		/// <summary>
		/// List of all Allow rights
		/// </summary>
		ArrayList m_AllowRights = new ArrayList();

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="i_name">Name for this role</param>
		/// <param name="i_description">Description of this role</param>
		public Role(string i_name, string i_description)
		{
			m_Name = i_name;
			m_Description = i_description;
		}

		/// <summary>
		/// Name of the role
		/// </summary>
		public string Name
		{
			get
			{
				return m_Name;
			}
		}

		/// <summary>
		/// Short description of the role
		/// </summary>
		public string Description
		{
			get
			{
				return m_Description;
			}
		}

		/// <summary>
		/// Inserts an allow right. If right already exists for this
		/// resource - replaces the existing right with the new right.
		/// </summary>
		/// <param name="i_right">the right</param>
		public void AddAllowRight(Right i_right)
		{
			// We currently support only one right per resource
			Right r = GetResourceRight(i_right.Resource);

			lock(this)
			{
				if(r != null)
				{
					m_AllowRights.Remove(r);
				}
				
				m_AllowRights.Add(i_right);
			}
		}

		/// <summary>
		/// Removes the specified right
		/// </summary>
		/// <param name="i_res">right to remove</param>
		/// <exception cref="ArgumentOutOfRangeException"></exception>
		public void RemoveAllowRight(IResource i_res)
		{
			Right r = GetResourceRight(i_res);

			lock(this)
			{
				if(r != null)
					m_AllowRights.Remove(r);
				else
					throw new ArgumentOutOfRangeException("Unable to find supplied right","Unable to find supplied right");
			}
		}

		/// <summary>
		/// Empties the rights container
		/// </summary>
		public void RemoveAllAllowRights()
		{
			lock(this)
			{
				m_AllowRights.Clear();
			}
		}

		/// <summary>
		/// Checks if this Role has a right that protects the same resource as i_needed
		/// </summary>
		/// <param name="i_needed">The Right to check against</param>
		/// <returns>True or False</returns>
		public bool HasAtLeastRight(Right i_needed)
		{
			Right r = GetResourceRight(i_needed.Resource);
			if(r != null)
			{
				return r.HasMinimumAccess(i_needed.Access);
			}
			
			return false;
		}

		/// <summary>
		/// Finds the first Right that represents the supplied resource
		/// </summary>
		/// <param name="i_res">The resource to look for</param>
		/// <returns>first Right that represents the supplied resource.
		/// Returns null if there is no Right for this resource</returns>
		Right GetResourceRight(IResource i_res)
		{
			foreach( Right a in m_AllowRights)
			{
				if(a.Matches(i_res))
					return a;
			}
			return null;
		}

		/// <summary>
		/// The size of the AllwRights array
		/// </summary>
		public int NumAllowRights
		{
			get
			{
				return m_AllowRights.Count;
			}
		}
	}
}
